//
//  BidirectionalBindDispose.swift
//  CSBind
//
//  Created by 万孟超 on 2023/12/22.
//

import Foundation

/// 双向绑定垃圾回收站
/// 一个回收站实例只能产生一个绑定事件
/// 再次绑定之后，第一次绑定将失效
public class CSBidirectionalBindDispose: CSBindDispose {
    /// 绑定操作者
    private var lOperator: CSBindOperatorRelease?
    /// 绑定操作者
    private var rOperator: CSBindOperatorRelease?
    
    /// 构造器
    /// - Parameters:
    ///   - lOperator: 绑定操作者
    ///   - rOperator: 绑定操作者
    convenience private init(lOperator: CSBindOperatorRelease?, rOperator: CSBindOperatorRelease?) {
        self.init()
        self.lOperator = lOperator
        self.rOperator = rOperator
    }
    
    // MARK -- 键值都是KeyPath类型
    
    /// 双向绑定 类方法暂时不开放，因为目前不考虑把 `UnidirectionalBindDispose` 类 暴露出去
    /// - Parameters:
    ///   - lBinder: 绑定者
    ///   - lBinderKeyPath: 绑定者的键值KeyPath
    ///   - rBinder: 绑定者
    ///   - rBinderKeyPath: 绑定者的键值KeyPath
    /// - Returns: 双向绑定回收站
    public class final func bind<LT, RT, ValueType>(_ lBinder: LT?, _ lBinderKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ rBinder: RT?, _ rBinderKeyPath: ReferenceWritableKeyPath<RT, ValueType>) -> Self where ValueType: Any, LT: NSObject, RT: NSObject {
        let lOperator = create(lBinder, lBinderKeyPath, rBinder, rBinderKeyPath) as? any CSBindOperatorRelease
        let rOperator = create(rBinder, rBinderKeyPath, lBinder, lBinderKeyPath) as? any CSBindOperatorRelease
        return CSBidirectionalBindDispose(lOperator: lOperator, rOperator: rOperator) as! Self
    }
    
    /// 双向绑定
    /// - Parameters:
    ///   - lBinder: 绑定者
    ///   - lBinderKeyPath: 绑定者的键值KeyPath
    ///   - rBinder: 绑定者
    ///   - rBinderKeyPath: 绑定者的键值KeyPath
    public override func bind<LT, RT, ValueType>(_ lBinder: LT?, _ lBinderKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ rBinder: RT?, _ rBinderKeyPath: ReferenceWritableKeyPath<RT, ValueType>) where ValueType: Any, LT: NSObject, RT: NSObject {
        lOperator = create(lBinder, lBinderKeyPath, rBinder, rBinderKeyPath) as? any CSBindOperatorRelease
        rOperator = create(rBinder, rBinderKeyPath, lBinder, lBinderKeyPath) as? any CSBindOperatorRelease
    }
    
    // MARK -- 键值都是String类型
    
    /// 双向绑定 类方法暂时不开放，因为目前不考虑把 `UnidirectionalBindDispose` 类 暴露出去
    /// - Parameters:
    ///   - lBinder: 绑定者
    ///   - lBinderKeyPath: 绑定者的键值KeyPath
    ///   - rBinder: 绑定者
    ///   - rBinderKeyPath: 绑定者的键值KeyPath
    /// - Returns: 双向绑定回收站
    public class final func bind<LT, RT>(_ lBinder: LT?, _ lBinderKeyPath: String, _ rBinder: RT?, _ rBinderKeyPath: String) -> Self where LT: NSObject, RT: NSObject {
        let lOperator = create(lBinder, lBinderKeyPath, rBinder, rBinderKeyPath) as? any CSBindOperatorRelease
        let rOperator = create(rBinder, rBinderKeyPath, lBinder, lBinderKeyPath) as? any CSBindOperatorRelease
        return CSBidirectionalBindDispose(lOperator: lOperator, rOperator: rOperator) as! Self
    }
    
    /// 双向绑定
    /// - Parameters:
    ///   - lBinder: 绑定者
    ///   - lBinderKeyPath: 绑定者的键值KeyPath
    ///   - rBinder: 绑定者
    ///   - rBinderKeyPath: 绑定者的键值KeyPath
    public override func bind<LT, RT>(_ lBinder: LT?, _ lBinderKeyPath: String, _ rBinder: RT?, _ rBinderKeyPath: String) where LT: NSObject, RT: NSObject {
        lOperator = create(lBinder, lBinderKeyPath, rBinder, rBinderKeyPath) as? any CSBindOperatorRelease
        rOperator = create(rBinder, rBinderKeyPath, lBinder, lBinderKeyPath) as? any CSBindOperatorRelease
    }
    
    // MARK -- 左边是String 右边是KeyPath
    
    /// 双向绑定 类方法暂时不开放，因为目前不考虑把 `UnidirectionalBindDispose` 类 暴露出去
    /// - Parameters:
    ///   - lBinder: 绑定者
    ///   - lBinderKeyPath: 绑定者的键值KeyPath
    ///   - rBinder: 绑定者
    ///   - rBinderKeyPath: 绑定者的键值KeyPath
    /// - Returns: 双向绑定回收站
    public class final func bind<LT, RT, RV>(_ lBinder: LT?, _ lBinderKeyPath: String, _ rBinder: RT?, _ rBinderKeyPath: ReferenceWritableKeyPath<RT, RV>) -> Self where RV: Any, LT: NSObject, RT: NSObject {
        let lOperator = create(lBinder, lBinderKeyPath, rBinder, rBinderKeyPath) as? any CSBindOperatorRelease
        let rOperator = create(rBinder, rBinderKeyPath, lBinder, lBinderKeyPath) as? any CSBindOperatorRelease
        return CSBidirectionalBindDispose(lOperator: lOperator, rOperator: rOperator) as! Self
    }
    
    /// 双向绑定
    /// - Parameters:
    ///   - lBinder: 绑定者
    ///   - lBinderKeyPath: 绑定者的键值KeyPath
    ///   - rBinder: 绑定者
    ///   - rBinderKeyPath: 绑定者的键KeyPathString
    public override func bind<LT, RT, RV>(_ lBinder: LT?, _ lBinderKeyPath: String, _ rBinder: RT?, _ rBinderKeyPath: ReferenceWritableKeyPath<RT, RV>) where RV: Any, LT: NSObject, RT: NSObject {
        lOperator = create(lBinder, lBinderKeyPath, rBinder, rBinderKeyPath) as? any CSBindOperatorRelease
        rOperator = create(rBinder, rBinderKeyPath, lBinder, lBinderKeyPath) as? any CSBindOperatorRelease
    }
    
    // MARK -- 左边是KeyPath 右边是String
    
    /// 双向绑定 类方法暂时不开放，因为目前不考虑把 `UnidirectionalBindDispose` 类 暴露出去
    /// - Parameters:
    ///   - lBinder: 绑定者
    ///   - lBinderKeyPath: 绑定者的键值KeyPath
    ///   - rBinder: 绑定者
    ///   - rBinderKeyPath: 绑定者的键值KeyPathString
    /// - Returns: 双向绑定回收站
    public class final func bind<LT, RT, LV>(_ lBinder: LT?, _ lBinderKeyPath: ReferenceWritableKeyPath<LT, LV>, _ rBinder: RT?, _ rBinderKeyPath: String) -> Self where LV: Any, LT: NSObject, RT: NSObject {
        let lOperator = create(lBinder, lBinderKeyPath, rBinder, rBinderKeyPath) as? any CSBindOperatorRelease
        let rOperator = create(rBinder, rBinderKeyPath, lBinder, lBinderKeyPath) as? any CSBindOperatorRelease
        return CSBidirectionalBindDispose(lOperator: lOperator, rOperator: rOperator) as! Self
    }
    
    /// 双向绑定
    /// - Parameters:
    ///   - lBinder: 绑定者
    ///   - lBinderKeyPath: 绑定者的键值KeyPath
    ///   - rBinder: 绑定者
    ///   - rBinderKeyPath: 绑定者的键值KeyPathString
    public override func bind<LT, RT, LV>(_ lBinder: LT?, _ lBinderKeyPath: ReferenceWritableKeyPath<LT, LV>, _ rBinder: RT?, _ rBinderKeyPath: String) where LV: Any, LT: NSObject, RT: NSObject {
        lOperator = create(lBinder, lBinderKeyPath, rBinder, rBinderKeyPath) as? any CSBindOperatorRelease
        rOperator = create(rBinder, rBinderKeyPath, lBinder, lBinderKeyPath) as? any CSBindOperatorRelease
    }
    
    /// 取消绑定
    /// 取消绑定之后，只有重新绑定才会生效
    public override func free() {
        lOperator?.free()
        lOperator = nil
        rOperator?.free()
        rOperator = nil
    }
    
    /// 暂停绑定
    /// 暂时停止绑定，和`run`可以配套使用
    public override func pause() {
        lOperator?.pause()
        rOperator?.pause()
    }
    
    /// 启动绑定
    /// 绑定暂停后，调用此方法可以重新启动绑定
    public override func run() {
        lOperator?.run()
        rOperator?.run()
    }
    
    /// 刷新是否忽略相同值
    override func freshIgnoreSameValue() {
        lOperator?.freshIgnoreSameValue(isIgnoreSameValue)
        rOperator?.freshIgnoreSameValue(isIgnoreSameValue)
    }
    
    override func updateIgnoreTimes() {
        lOperator?.updateIgnoreTimes(bindIgnoreTimes)
        rOperator?.updateIgnoreTimes(bindIgnoreTimes)
    }
    
    override func updateBindIgnoreTimesByIgnoreValue() {
        lOperator?.updateBindIgnoreTimesByIgnoreValue(bindIgnoreTimesByIgnoreValue)
        rOperator?.updateBindIgnoreTimesByIgnoreValue(bindIgnoreTimesByIgnoreValue)
    }
    
    /// 立即生效一次
    public override func immediatelyAvaliable() {
        lOperator?.immediatelyExcute()
        rOperator?.immediatelyExcute()
    }
}

extension CSBidirectionalBindDispose: CSOperatorBindable { }
